package ch.usi.inf.pf2.gui;

import javax.swing.table.AbstractTableModel;

import ch.usi.inf.pf2.Sheet;
import ch.usi.inf.pf2.cell.Data;
import ch.usi.inf.pf2.cell.Text;
import ch.usi.inf.pf2.editor.TextInsert;
import ch.usi.inf.pf2.editor.UndoRedoStack;

/**
 * 
 * @author Thomas Mantegazzi 
 * 
 * The table model of the Spread Sheet table
 * 
 */

public class SpreadSheetTableModel extends AbstractTableModel {

	private String[] columnNames;
	private int[] rowNumbers;
	private Object[][] data;
	private Sheet sheet;
	private UndoRedoStack stack;
	private int defaultRowHight;

	/**
	 * Constructor of the class
	 * 
	 * @param columnNames
	 *            A string array with the names of the columns
	 * @param data
	 *            the row data
	 */
	public SpreadSheetTableModel(String[] columnNames, Object[][] data,
			Sheet sheet, UndoRedoStack stack) {
		this.columnNames = columnNames;
		this.rowNumbers = createRowIndex(data.length);
		this.data = data;
		this.sheet = sheet;
		this.stack = stack;
		this.defaultRowHight = 15;
	}

	@Override
	public void fireTableDataChanged() {
		// TODO Auto-generated method stub
		super.fireTableDataChanged();
	}

	/**
	 * Returns the default row hight
	 * 
	 * @return and int representing the DefaultRow Hight of the model
	 */
	public int getDefaultRowHight() {
		return defaultRowHight;
	}

	/**
	 * Create an int array with the row index, from one to the row Dimention
	 * passed as a parameter
	 * 
	 * @param rowDim
	 *            the row dimension which is the dimension of the Index
	 * @return an int array that contains the indexes of the rows of the table
	 */
	private int[] createRowIndex(int rowDim) {
		int[] rowIndex = new int[rowDim];
		for (int i = 0; i < rowIndex.length; i++) {
			rowIndex[i] = i + 1;
		}
		return rowIndex;
	}

	/**
	 * This method the int[] of the rowNumers
	 * 
	 * @return the int[] of the row Idexes
	 */
	public int[] getRowNumers() {
		return rowNumbers;
	}

	/**
	 * get the number of rows
	 */
	@Override
	public int getRowCount() {
		return rowNumbers.length;
	}

	/**
	 * get the value at a defined rowIndex and IolumnIndex
	 */
	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		return data[rowIndex][columnIndex];
	}

	/**
	 * Set a the Value given as a parameter in the cell at the given position.
	 * (and notify it to the listener of the class but not to the class
	 * Listener)
	 */
	public void setValueAt(Object value, int row, int col) {
		if (value != null) {
			if (value instanceof String) {
				TextInsert text = new TextInsert(sheet, row + 1, col + 1,
						(String) value);
				stack.addActionToUndoStack(text);
				sheet.insertDataAtCell((String) value, col + 1, row + 1);
				fireTableCellUpdated(row, col);
			} else {
				TextInsert text = new TextInsert(sheet, row + 1, col + 1,
						((Data) value).toString());
				stack.addActionToUndoStack(text);
				sheet.insertDataAtCell(((Data) value).getInstance(), col + 1,
						row + 1);
				fireTableCellUpdated(row, col);
			}
		} else {
			sheet.insertDataAtCell("", col + 1, row + 1);
			fireTableCellUpdated(row, col);
		}
		sheet.setHasBeenSaved(false);
	}

	/**
	 * get the number of columns
	 */
	@Override
	public int getColumnCount() {
		return columnNames.length;
	}

	/**
	 * Say to the table if a cell can be edited, in this model every cell can be
	 * edited.
	 */
	public boolean isCellEditable(int row, int col) {
		// System.out.println("here");
		return true;
	}

	/**
	 * return the class of the given column
	 */
	public Class getColumnClass(int c) {
		return Text.class;
	}

}
